本文同步刊載於個人連載網站
Day 25 寫到,測試可以把已經確認過的行為留下來,讓後面的修改持續重新面對這些期待。
但即使測試全部通過,我的開發流程還不會停在這裡。
因為測試主要在回答:
已經被寫下來的期待,有沒有成立?
但還有另一個問題:
即使功能真的做對了,這個實作方式也適合這套系統嗎?
這就是我現在還會再做 review 的原因。
現在開始 Coding 以前,我通常已經先走過規格和 design 的討論。
這些文件不只描述最後功能要做到什麼,也常會包含:
所以功能完成之後,我會再把實作拿回來和 design 對照。
不是只確認:
最後畫面有沒有動。
而是:
程式最後是不是照著前面確認過的方式做。
因為同一個功能結果,通常不只一種實作方式。
有些做法可以讓測試全部通過,功能也真的正常。
但如果它已經繞過原本設計好的責任分工,或者改成另一套沒有先討論過的方式,這件事情仍然需要被看見。
對我來說,design 不只是 Coding 開始以前的計畫。
它也是 Coding 完成之後,拿來重新確認實作方向的依據。
我現在還會再看另一個面向:
這次實作,有沒有符合這個專案原本的工程方式。
這和「有沒有照這次 design 做」不完全一樣。
design 比較像是在看這一次修改。
這一層則是把視角拉到整套既有系統。
原本責任怎麼分?
前後端怎麼交換資料?
不同 repo 彼此怎麼配合?
哪些邊界已經被建立?
一個專案做久之後,這些東西會逐漸形成穩定的結構。
如果每一次新增功能,都只想:
這次怎麼最快做出來?
很容易每個地方都長出不同做法。
單看某一個功能可能都可以運作,但整套系統會越來越難理解,也越來越難維持原本的分工。
所以這一層真正問的是:
這個做法放進目前這套系統裡,還合理嗎?
對我來說,更接近:
不是只把功能塞進專案,而是要讓它長進原本的系統裡。
我目前有一個自訂的雙軸審查方式。
所謂「雙軸」,就是 review 時固定看兩件事:
第一個:
有沒有符合這次 design。
第二個:
有沒有符合既有系統的工程方式。
這兩個面向分開看很重要。
因為一個實作可能:
所以 review 對我來說,不只是再檢查一次「功能有沒有壞」。
而是重新確認:
前面做出的工程判斷,有沒有真的被守住。
除了雙軸審查,我現在也會使用 Spectra audit 裡的三角色對抗式 review。
這兩件事不是三個並列的 review 類型。
雙軸比較像是在決定:
我要檢查哪些事情。
對抗式 review 則是在改變:
我要用什麼方式去檢查。
一般實作時,主要問題通常是:
我要怎麼把這個需求做出來?
對抗式 review 會故意站到另一個位置:
我要怎麼找出這個實作可能出問題的地方?
它會主動去挑戰:
所以它不是再多加一個 review 面向。
而是用更刻意找問題的方式,重新檢查前面已經定好的那些面向。
到這裡,我會把測試和 review 的差別看得比較清楚。
測試比較像是在問:
那些已經被定義的行為,有沒有成立?
review 則會再問:
即使功能成立,實作本身有沒有偏離前面的設計與系統邊界?
這兩層都需要。
因為如果只看功能結果,很容易變成:
每個功能單獨都能跑。
但整套程式逐漸長成彼此不一致的做法。
前面花時間討論的責任分工、design 和工程決策,也可能在真正實作時被繞掉。
所以我現在不只想知道:
「功能有沒有做對?」
還會再問:
「它是不是用適合這套系統的方式被做出來?」